{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "from keras.models import Model\n",
    "from keras.layers import Input, Dense, RepeatVector\n",
    "from keras.layers.merge import Add, Subtract, Multiply, Average, Maximum, Minimum, Concatenate, Dot\n",
    "from keras import backend as K\n",
    "import json\n",
    "from collections import OrderedDict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def format_decimal(arr, places=6):\n",
    "    return [round(x * 10**places) / 10**places for x in arr]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "DATA = OrderedDict()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**[merge.Add.0]**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "random_seed = 100\n",
    "data_in_shape = (6,)\n",
    "\n",
    "layer_0 = Input(shape=data_in_shape)\n",
    "layer_1a = Dense(2, activation='linear')(layer_0)\n",
    "layer_1b = Dense(2, activation='linear')(layer_0)\n",
    "layer_2 = Add()([layer_1a, layer_1b])\n",
    "model = Model(inputs=layer_0, outputs=layer_2)\n",
    "\n",
    "np.random.seed(random_seed)\n",
    "data_in = np.expand_dims(2 * np.random.random(data_in_shape) - 1, axis=0)\n",
    "\n",
    "# set weights to random (use seed for reproducibility)\n",
    "weights = []\n",
    "for i, w in enumerate(model.get_weights()):\n",
    "    np.random.seed(random_seed + i)\n",
    "    weights.append(2 * np.random.random(w.shape) - 1)\n",
    "model.set_weights(weights)\n",
    "\n",
    "result = model.predict(data_in)\n",
    "data_out_shape = result[0].shape\n",
    "data_in_formatted = format_decimal(data_in.ravel().tolist())\n",
    "data_out_formatted = format_decimal(result[0].ravel().tolist())\n",
    "\n",
    "DATA['merge.Add.0'] = {\n",
    "    'input': {'data': data_in_formatted, 'shape': data_in_shape},\n",
    "    'weights': [{'data': format_decimal(w.ravel().tolist()), 'shape': w.shape} for w in weights],\n",
    "    'expected': {'data': data_out_formatted, 'shape': data_out_shape}\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**[merge.Add.1]**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "random_seed = 100\n",
    "data_in_shape = (6,)\n",
    "\n",
    "layer_0 = Input(shape=data_in_shape)\n",
    "layer_1a = Dense(2, activation='linear')(layer_0)\n",
    "layer_1b = Dense(2, activation='linear')(layer_0)\n",
    "layer_1c = Dense(2, activation='linear')(layer_0)\n",
    "layer_2 = Add()([layer_1a, layer_1b, layer_1c])\n",
    "model = Model(inputs=layer_0, outputs=layer_2)\n",
    "\n",
    "np.random.seed(random_seed)\n",
    "data_in = np.expand_dims(2 * np.random.random(data_in_shape) - 1, axis=0)\n",
    "\n",
    "# set weights to random (use seed for reproducibility)\n",
    "weights = []\n",
    "for i, w in enumerate(model.get_weights()):\n",
    "    np.random.seed(random_seed + i)\n",
    "    weights.append(2 * np.random.random(w.shape) - 1)\n",
    "model.set_weights(weights)\n",
    "\n",
    "result = model.predict(data_in)\n",
    "data_out_shape = result[0].shape\n",
    "data_in_formatted = format_decimal(data_in.ravel().tolist())\n",
    "data_out_formatted = format_decimal(result[0].ravel().tolist())\n",
    "\n",
    "DATA['merge.Add.1'] = {\n",
    "    'input': {'data': data_in_formatted, 'shape': data_in_shape},\n",
    "    'weights': [{'data': format_decimal(w.ravel().tolist()), 'shape': w.shape} for w in weights],\n",
    "    'expected': {'data': data_out_formatted, 'shape': data_out_shape}\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**[merge.Add.2]**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "random_seed = 100\n",
    "data_in_shape = (6,)\n",
    "\n",
    "layer_0 = Input(shape=data_in_shape)\n",
    "layer_1a = Dense(2, activation='linear')(layer_0)\n",
    "layer_1b = Dense(2, activation='linear')(layer_0)\n",
    "layer_1c = Dense(2, activation='linear')(layer_0)\n",
    "layer_1d = Dense(2, activation='linear')(layer_0)\n",
    "layer_2 = Add()([layer_1a, layer_1b, layer_1c, layer_1d])\n",
    "model = Model(inputs=layer_0, outputs=layer_2)\n",
    "\n",
    "np.random.seed(random_seed)\n",
    "data_in = np.expand_dims(2 * np.random.random(data_in_shape) - 1, axis=0)\n",
    "\n",
    "# set weights to random (use seed for reproducibility)\n",
    "weights = []\n",
    "for i, w in enumerate(model.get_weights()):\n",
    "    np.random.seed(random_seed + i)\n",
    "    weights.append(2 * np.random.random(w.shape) - 1)\n",
    "model.set_weights(weights)\n",
    "\n",
    "result = model.predict(data_in)\n",
    "data_out_shape = result[0].shape\n",
    "data_in_formatted = format_decimal(data_in.ravel().tolist())\n",
    "data_out_formatted = format_decimal(result[0].ravel().tolist())\n",
    "\n",
    "DATA['merge.Add.2'] = {\n",
    "    'input': {'data': data_in_formatted, 'shape': data_in_shape},\n",
    "    'weights': [{'data': format_decimal(w.ravel().tolist()), 'shape': w.shape} for w in weights],\n",
    "    'expected': {'data': data_out_formatted, 'shape': data_out_shape}\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### export for Keras.js tests"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "filename = '../../../test/data/layers/merge/Add.json'\n",
    "if not os.path.exists(os.path.dirname(filename)):\n",
    "    os.makedirs(os.path.dirname(filename))\n",
    "with open(filename, 'w') as f:\n",
    "    json.dump(DATA, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\"merge.Add.0\": {\"input\": {\"data\": [0.08681, -0.443261, -0.150965, 0.689552, -0.990562, -0.756862], \"shape\": [6]}, \"weights\": [{\"data\": [0.08681, -0.443261, -0.150965, 0.689552, -0.990562, -0.756862, 0.341498, 0.651706, -0.726587, 0.150187, 0.782644, -0.581596], \"shape\": [6, 2]}, {\"data\": [0.032797, 0.141335], \"shape\": [2]}, {\"data\": [0.195363, 0.351974, -0.401437, 0.461481, 0.157479, 0.618035, -0.665503, -0.37571, -0.284137, -0.016505, -0.019604, 0.78882], \"shape\": [6, 2]}, {\"data\": [-0.135778, -0.651569], \"shape\": [2]}], \"expected\": {\"data\": [0.49239, -1.106355], \"shape\": [2]}}, \"merge.Add.1\": {\"input\": {\"data\": [0.08681, -0.443261, -0.150965, 0.689552, -0.990562, -0.756862], \"shape\": [6]}, \"weights\": [{\"data\": [0.08681, -0.443261, -0.150965, 0.689552, -0.990562, -0.756862, 0.341498, 0.651706, -0.726587, 0.150187, 0.782644, -0.581596], \"shape\": [6, 2]}, {\"data\": [0.032797, 0.141335], \"shape\": [2]}, {\"data\": [0.195363, 0.351974, -0.401437, 0.461481, 0.157479, 0.618035, -0.665503, -0.37571, -0.284137, -0.016505, -0.019604, 0.78882], \"shape\": [6, 2]}, {\"data\": [-0.135778, -0.651569], \"shape\": [2]}, {\"data\": [-0.704159, -0.543403, 0.614987, -0.403051, -0.628587, 0.544275, -0.189121, 0.991809, -0.028349, 0.30284, 0.201092, -0.953154], \"shape\": [6, 2]}, {\"data\": [-0.83252, -0.332987], \"shape\": [2]}], \"expected\": {\"data\": [-0.833489, -0.284697], \"shape\": [2]}}, \"merge.Add.2\": {\"input\": {\"data\": [0.08681, -0.443261, -0.150965, 0.689552, -0.990562, -0.756862], \"shape\": [6]}, \"weights\": [{\"data\": [0.08681, -0.443261, -0.150965, 0.689552, -0.990562, -0.756862, 0.341498, 0.651706, -0.726587, 0.150187, 0.782644, -0.581596], \"shape\": [6, 2]}, {\"data\": [0.032797, 0.141335], \"shape\": [2]}, {\"data\": [0.195363, 0.351974, -0.401437, 0.461481, 0.157479, 0.618035, -0.665503, -0.37571, -0.284137, -0.016505, -0.019604, 0.78882], \"shape\": [6, 2]}, {\"data\": [-0.135778, -0.651569], \"shape\": [2]}, {\"data\": [-0.704159, -0.543403, 0.614987, -0.403051, -0.628587, 0.544275, -0.189121, 0.991809, -0.028349, 0.30284, 0.201092, -0.953154], \"shape\": [6, 2]}, {\"data\": [-0.83252, -0.332987], \"shape\": [2]}, {\"data\": [-0.98287, 0.908613, -0.10087, 0.220438, 0.70412, 0.47762, 0.948863, 0.714924, 0.710821, 0.719052, -0.295442, -0.575936], \"shape\": [6, 2]}, {\"data\": [-0.67459, 0.509562], \"shape\": [2]}], \"expected\": {\"data\": [-1.481201, 0.350542], \"shape\": [2]}}}\n"
     ]
    }
   ],
   "source": [
    "print(json.dumps(DATA))"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
